/*
 * mebs-list.h
 *
 *  Created on: May 31, 2016
 *      Author: zhangzm
 */

#ifndef URSAX_LIST_H_
#define URSAX_LIST_H_

typedef struct UrsaXList
{
	struct UrsaXList **pre_next;
	struct UrsaXList *next;
} UrsaXList;

#define INIT_URSAX_LIST(node) 	\
{								\
	(node).pre_next = &(node).next; \
	(node).next = &(node);			\
}

#define IS_EMPTY_LIST(pnode)	\
	((pnode) == (pnode)->next)

#define INSERT_AFTER_NODE(node, add_node) 		\
{												\
	(add_node)->pre_next = &(node)->next;		\
	(add_node)->next = (node)->next;			\
	(node)->next->pre_next = &(add_node)->next;	\
	(node)->next = (add_node);					\
}

#define INSERT_BEFORE_NODE(node, add_node)		\
{												\
	(add_node)->next = (node);					\
	(add_node)->pre_next = (node)->pre_next;	\
	*(node)->pre_next = (add_node);		\
	(node)->pre_next = &(add_node)->next;		\
}

#define PRE_NODE(node) container_of((node)->pre_next, MebsList, next)
#define NEXT_NODE(node) ((node)->next)

#define DELETE_NODE(node) 		\
{								\
	*(node)->pre_next = (node)->next;\
	(node)->next->pre_next = (node)->pre_next;\
	INIT_URSAX_LIST(*node);				\
}

#define MV_LIST(phead_des, phead_src)						\
		INIT_URSAX_LIST(*(phead_des));						\
		if(!IS_EMPTY_LIST(phead_src)){						\
			typeof(phead_src) __pre__ = PRE_NODE(phead_src);\
			DELETE_NODE(phead_src);							\
			INSERT_AFTER_NODE(__pre__, phead_des);			\
		}

#define CAT_LIST(phead_des, phead_src)								\
		if(!IS_EMPTY_LIST(phead_src)){								\
			*(phead_des)->pre_next = (phead_src)->next;				\
			(phead_src)->next->pre_next = (phead_des)->pre_next;	\
			*(phead_src)->pre_next = (phead_des);					\
			(phead_des)->pre_next = (phead_src)->pre_next;			\
			INIT_URSAX_LIST(*phead_src);								\
		}


#define NODE_FOR_EACH(head, p) \
		for(UrsaXList *p = (head)->next, *q = p->next; p != (head); p = q, q = q->next)

#define NODE_FOR_R_EACH(head, p) \
		for(MebsList *p = PRE_NODE(head), *pp = PRE_NODE(p); p != (head); p = pp, pp = PRE_NODE(pp))

#endif /* URSAX_LIST_H_ */
